package mornd.test3;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;

import java.util.Set;

/**
 * @author: mornd
 * @dateTime: 2023/5/5 - 12:51
 */
public class AtBeanPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        CachingMetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory();
        try {
            // 此方式读是不走类加载那一步，效率比反射高
            MetadataReader metadataReader =
                    metadataReaderFactory.getMetadataReader(new ClassPathResource("mornd/test3/Config.class"));

            // 拿到类中被 @Bean 注解标注的方法
            Set<MethodMetadata> methods =
                    metadataReader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());

            for (MethodMetadata method : methods) {
                // 获取 @Bean 注解的属性值
                String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();

                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();

                // 以名称 config 的bean为工厂类，method.getMethodName() 为工厂方法
                builder.setFactoryMethodOnBean(method.getMethodName(), "config");
                // 设置工厂方法的装配模式 (解析工厂方法的参数，从容器中找)
                builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);

                if(initMethod.length() > 0) {
                    // 设置 bean 的初始化方法
                    builder.setInitMethodName(initMethod);
                }

                AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

                // 注册 beanDefinition
                registry.registerBeanDefinition(method.getMethodName(), beanDefinition);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}
